/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package trumpet.core.buddylist;

import java.io.*;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.*;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.xml.sax.SAXException;
import trumpet.core.User;
import org.w3c.dom.*;

/**
 *
 * @author Artur
 */
public class CollectionAdapterXmlFile extends CollectionAdapterAbstract {

    public CollectionAdapterXmlFile() {

    }
    
    public CollectionAdapterXmlFile(String path) {
        this.loadFile(path);
        try {
            this.setDocumentBuldier();
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(CollectionAdapterXmlFile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(CollectionAdapterXmlFile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CollectionAdapterXmlFile.class.getName()).log(Level.SEVERE, null, ex);
        }

        getElementById(0);

    }

    public void loadFile(String path) {
        this.file = new File(path);
        try {
            if( ! (file.exists() && file.canRead()) ) {
                    throw new IOException("Cant not read file from " +
                                           file.getAbsolutePath());
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void setDocumentBuldier() throws ParserConfigurationException,
                                             SAXException, IOException {
        if (this.file != null) {
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

            this.document = builder.parse(this.file);
        }

    }

    private Node getRootNode() {
       return this.document.getFirstChild();
    }

    private Element createDomElement(String name) {
        return this.document.createElement(name);
    }
    private Element createDomElement(String name, String content) {
        Element element = this.createDomElement(name);
        element.appendChild(this.document.createTextNode(content));
        return element;
    }

    /*
     * @TODO exception
     */
    private Element getElementByName(Element parent, String name) {
        try {
            if (parent.getElementsByTagName(name).getLength() != 1) {
                throw new Exception("Found more tags than one");
            }
        } catch (Exception ex) {
            Logger.getLogger(CollectionAdapterXmlFile.class.getName()).log(Level.SEVERE, null, ex);
        }

        return (Element) parent.getElementsByTagName(name).item(0);
    }

    private Element getElementById(int id) {
        NodeList list = getRootNode().getChildNodes();
        Element buddy = (Element) getRootNode();
        for (int i = 0; i < list.getLength(); i++) {
            if(list.item(i) instanceof Element) {
               int itemId = Integer.parseInt(list.item(i).getAttributes()
                                                 .getNamedItem("id")
                                                 .getTextContent());

                if (itemId == id) {
                    buddy = (Element) list.item(i);
                }
            }
        }
        return buddy;
    }

    private int countUsers() {
        int elements = 0;
        NodeList list = getRootNode().getChildNodes();
        
        for(int i = 0; i < list.getLength(); i++) {
          if(list.item(i) instanceof Element) {
              elements++;
          }
        }

        return elements;
    }
    private Element createUserEntry(User user) {
        Element buddy = this.createDomElement(NODE_BUDDY);
        buddy.setAttribute(ATTR_ID, user.getId().toString());
        buddy.appendChild(this.createDomElement(NODE_NAME, user.getName()));
        buddy.appendChild(this.createDomElement(NODE_SURNAME, user.getSurname()));
        buddy.appendChild(this.createDomElement(NODE_GENER, user.getGener().toString()));
        buddy.appendChild(this.createDomElement(NODE_IPADDRESS, user.getIp()));

        return buddy;
    }
    /**
     * Public methods
     *
     */

    @Override
    public int save() {
        try {
            Source source = new DOMSource(this.document);
            // Prepare the output file
            StreamResult result = new StreamResult(this.file);
            // Write the DOM document to the file
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.transform(source, result);
        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(CollectionAdapterXmlFile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(CollectionAdapterXmlFile.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return 1;
    }

    @Override
    public User[] getElements() {
        NodeList list = getRootNode().getChildNodes();
        User[] users = new User[this.countUsers()];

        int j = 0;

        for(int i = 0; i < list.getLength(); i++) {
          if(list.item(i) instanceof Element) {
              Element buddy = (Element) list.item(i);

              User user = new User();
              user.setName(this.getElementByName(buddy, NODE_NAME).getTextContent());
              user.setSurname(this.getElementByName(buddy, NODE_SURNAME).getTextContent());
              user.setIp(this.getElementByName(buddy, NODE_IPADDRESS).getTextContent());
              user.setGener(this.getElementByName(buddy, NODE_GENER).getTextContent());
              user.setId(Integer.parseInt(buddy.getAttribute(ATTR_ID)));

              users[j++] = user;

          }
        }
        return users;
    }
    @Override
    public File export(String path) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean addElement(User user) {
        Element buddy = this.createUserEntry(user);
        this.getRootNode().appendChild(buddy);
        
        return true;
    }

    @Override
    public void editElement(User user){
        Node oldData = (Node) this.getElementById(user.getId());
        if(oldData != null) {
            Element newData = this.createUserEntry(user);
            this.getRootNode().replaceChild(newData, oldData);
        }
    }

    @Override
    public User getElementAt(int index) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean deleteElementAt(int index) {
//        document.re
        Element buddyToDelete = this.getElementById(index);
        getRootNode().removeChild(buddyToDelete);

        return true;
    }

    private File file;
    private Document document;

    private static final String NODE_BUDDY = "user";
    private static final String NODE_NAME = "name";
    private static final String NODE_SURNAME = "surname";
    private static final String NODE_GENER = "gener";
    private static final String NODE_IPADDRESS = "ipaddress";

    private static final String ATTR_ID = "id";
}
